import java.io.*;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.*;
import java.util.UUID;

public class CinemaSystem1 {
    public static final String CONFIG_FILE = "cinema_config.properties";
    public static final String USERS_FILE = "users.txt";
    public static final String MOVIES_FILE = "movies.txt";

    public static void main(String[] args) {
        CinemaSystem1 cinema = new CinemaSystem1();
        cinema.start();
    }

    private UserManager1_1 userManager = new UserManager1_1();
    private MovieManager1_1 movieManager = new MovieManager1_1();
    private ScreeningManager1_1 screeningManager;
    private TicketManager1_1 ticketManager = new TicketManager1_1();
    private User currentUser;
    private Scanner scanner = new Scanner(System.in);

    public CinemaSystem1() {
        Map<String, ScreeningHall> halls = loadHalls();
        screeningManager = new ScreeningManager1_1(halls, movieManager, ticketManager);
    }

    private Map<String, ScreeningHall> loadHalls() {
        Map<String, ScreeningHall> map = new HashMap<>();
        map.put("黄金厅", new ScreeningHall("黄金厅", 8, 10));
        map.put("白银厅", new ScreeningHall("白银厅", 10, 12));
        map.put("翡翠厅", new ScreeningHall("翡翠厅", 7, 8));
        map.put("钻石厅", new ScreeningHall("钻石厅", 7, 8));
        map.put("宝石厅", new ScreeningHall("宝石厅", 8, 9));
        return map;
    }

    public void start() {
        userManager.loadUsersFromFile();
        movieManager.loadMoviesFromFile();

        while (true) {
            System.out.println("\n===== 万东影院管理系统 =====");
            System.out.println("1. 登录");
            System.out.println("2. 退出系统");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        login();
                        break;
                    case 2:
                        userManager.saveUsersToFile();
                        movieManager.saveMoviesToFile();
                        System.out.println("系统已退出");
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            }
        }
    }

    private void login() {
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();

        currentUser = userManager.authenticate(username, password);

        if (currentUser == null) {
            System.out.println("用户名或密码错误");
            return;
        }

        if (currentUser.isForcePasswordChange()) {
            changePasswordFirstLogin();
        }

        showRoleMenu();
    }

    private void changePasswordFirstLogin() {
        System.out.println("首次登录需要修改密码");
        System.out.print("输入新密码: ");
        String newPassword = scanner.nextLine();
        currentUser.setPassword(newPassword);
        currentUser.setForcePasswordChange(false);
        System.out.println("密码修改成功");
    }

    private void showRoleMenu() {
        if (currentUser instanceof Admin) {
            showAdminMenu();
        } else if (currentUser instanceof Manager) {
            showManagerMenu();
        } else if (currentUser instanceof FrontDesk) {
            showFrontDeskMenu();
        }
    }

    // 管理员菜单
    private void showAdminMenu() {
        while (true) {
            System.out.println("\n===== 管理员菜单 =====");
            System.out.println("1. 密码管理");
            System.out.println("2. 用户管理");
            System.out.println("3. 退出登录");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        adminPasswordMenu();
                        break;
                    case 2:
                        userManagementMenu();
                        break;
                    case 3:
                        currentUser = null;
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            }
        }
    }

    private void adminPasswordMenu() {
        System.out.println("\n--- 密码管理 ---");
        System.out.println("1. 修改自身密码");
        System.out.println("2. 重置用户密码");
        System.out.print("请选择: ");

        try {
            int choice = Integer.parseInt(scanner.nextLine());

            switch (choice) {
                case 1:
                    System.out.print("输入新密码: ");
                    String newPass = scanner.nextLine();
                    currentUser.setPassword(newPass);
                    System.out.println("密码修改成功");
                    break;
                case 2:
                    System.out.print("输入要重置的用户名: ");
                    String username = scanner.nextLine();
                    userManager.resetUserPassword(username);
                    System.out.println("密码已重置为123456");
                    break;
                default:
                    System.out.println("无效选择");
            }
        } catch (NumberFormatException e) {
            System.out.println("请输入数字选项");
        } catch (BusinessException e) {
            System.out.println(e.getMessage());
        }
    }

    private void userManagementMenu() {
        while (true) {
            System.out.println("\n--- 用户管理 ---");
            System.out.println("1. 列出所有用户");
            System.out.println("2. 添加用户");
            System.out.println("3. 删除用户");
            System.out.println("4. 查询用户");
            System.out.println("5. 修改用户");
            System.out.println("0. 返回");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        userManager.listAllUsers();
                        break;
                    case 2:
                        addUser();
                        break;
                    case 3:
                        deleteUser();
                        break;
                    case 4:
                        queryUser();
                        break;
                    case 5:
                        updateUser();
                        break;
                    case 0:
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            } catch (BusinessException e) {
                System.out.println(e.getMessage());
            }
        }
    }

    private void addUser() {
        System.out.print("用户ID: ");
        String userId = scanner.nextLine();
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("手机号: ");
        String phone = scanner.nextLine();

        System.out.println("用户类型 (1-管理员, 2-经理, 3-前台): ");
        int typeChoice = Integer.parseInt(scanner.nextLine());
        UserType userType = null;

        switch (typeChoice) {
            case 1: userType = UserType.ADMIN; break;
            case 2: userType = UserType.MANAGER; break;
            case 3: userType = UserType.FRONT_DESK; break;
            default: throw new BusinessException("无效用户类型");
        }

        userManager.addUser(userId, username, phone, userType);
        System.out.println("用户添加成功");
    }

    private void deleteUser() {
        System.out.print("输入要删除的用户名: ");
        String username = scanner.nextLine();
        userManager.deleteUser(username);
        System.out.println("用户删除成功");
    }

    private void queryUser() {
        System.out.print("输入查询用户名: ");
        String username = scanner.nextLine();
        userManager.queryUser(username);
    }

    private void updateUser() {
        System.out.print("输入要修改的用户名: ");
        String username = scanner.nextLine();
        System.out.print("新手机号: ");
        String phone = scanner.nextLine();

        System.out.println("新用户类型 (1-经理, 2-前台): ");
        int typeChoice = Integer.parseInt(scanner.nextLine());
        UserType newType = null;

        switch (typeChoice) {
            case 1: newType = UserType.MANAGER; break;
            case 2: newType = UserType.FRONT_DESK; break;
            default: throw new BusinessException("无效用户类型");
        }

        userManager.updateUser(username, newType, phone);
        System.out.println("用户信息更新成功");
    }

    // 经理菜单
    private void showManagerMenu() {
        while (true) {
            System.out.println("\n===== 经理菜单 =====");
            System.out.println("1. 密码管理");
            System.out.println("2. 影片管理");
            System.out.println("3. 排片管理");
            System.out.println("4. 查看销售数据");
            System.out.println("5. 退出登录");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        managerPasswordMenu();
                        break;
                    case 2:
                        movieManagementMenu();
                        break;
                    case 3:
                        screeningManagementMenu();
                        break;
                    case 4:
                        salesReportMenu();
                        break;
                    case 5:
                        currentUser = null;
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            }
        }
    }

    private void managerPasswordMenu() {
        System.out.println("\n--- 密码管理 ---");
        System.out.println("1. 修改自身密码");
        System.out.println("2. 重置前台密码");
        System.out.print("请选择: ");

        try {
            int choice = Integer.parseInt(scanner.nextLine());

            switch (choice) {
                case 1:
                    System.out.print("输入新密码: ");
                    String newPass = scanner.nextLine();
                    currentUser.setPassword(newPass);
                    System.out.println("密码修改成功");
                    break;
                case 2:
                    System.out.print("输入要重置的前台用户名: ");
                    String username = scanner.nextLine();
                    userManager.resetFrontDeskPassword(username);
                    System.out.println("密码已重置为123456");
                    break;
                default:
                    System.out.println("无效选择");
            }
        } catch (NumberFormatException e) {
            System.out.println("请输入数字选项");
        } catch (BusinessException e) {
            System.out.println(e.getMessage());
        }
    }

    private void movieManagementMenu() {
        while (true) {
            System.out.println("\n--- 影片管理 ---");
            System.out.println("1. 列出所有影片");
            System.out.println("2. 添加影片");
            System.out.println("3. 修改影片");
            System.out.println("4. 删除影片");
            System.out.println("5. 查询影片");
            System.out.println("0. 返回");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        movieManager.listAllMovies();
                        break;
                    case 2:
                        addMovie();
                        break;
                    case 3:
                        updateMovie();
                        break;
                    case 4:
                        deleteMovie();
                        break;
                    case 5:
                        searchMovie();
                        break;
                    case 0:
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            } catch (BusinessException e) {
                System.out.println(e.getMessage());
            }
        }
    }

    private void addMovie() {
        System.out.print("片名: ");
        String title = scanner.nextLine();
        System.out.print("导演: ");
        String director = scanner.nextLine();
        System.out.print("主演(用逗号分隔): ");
        String[] stars = scanner.nextLine().split(",");
        System.out.print("剧情简介: ");
        String description = scanner.nextLine();
        System.out.print("时长(分钟): ");
        int duration = Integer.parseInt(scanner.nextLine());
        System.out.print("评分(0-10): ");
        double rating = Double.parseDouble(scanner.nextLine());

        movieManager.addMovie(title, director, stars, description, duration, rating);
        System.out.println("影片添加成功");
    }

    private void updateMovie() {
        System.out.print("输入要修改的电影ID: ");
        String movieId = scanner.nextLine();
        System.out.print("新片名: ");
        String title = scanner.nextLine();
        System.out.print("新导演: ");
        String director = scanner.nextLine();
        System.out.print("新主演(用逗号分隔): ");
        String[] stars = scanner.nextLine().split(",");
        System.out.print("新剧情简介: ");
        String description = scanner.nextLine();
        System.out.print("新时长(分钟): ");
        int duration = Integer.parseInt(scanner.nextLine());
        System.out.print("新评分(0-10): ");
        double rating = Double.parseDouble(scanner.nextLine());

        movieManager.updateMovie(movieId, title, director, stars, description, duration, rating);
        System.out.println("影片更新成功");
    }

    private void deleteMovie() {
        System.out.print("输入要删除的电影ID: ");
        String movieId = scanner.nextLine();
        movieManager.deleteMovie(movieId);
        System.out.println("影片删除成功");
    }

    private void searchMovie() {
        System.out.print("输入搜索关键词(片名/导演/主演): ");
        String keyword = scanner.nextLine();
        movieManager.searchMovies(keyword);
    }

    private void screeningManagementMenu() {
        while (true) {
            System.out.println("\n--- 排片管理 ---");
            System.out.println("1. 列出所有场次");
            System.out.println("2. 添加场次");
            System.out.println("3. 修改场次");
            System.out.println("4. 删除场次");
            System.out.println("5. 自动排片");
            System.out.println("0. 返回");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        screeningManager.listScreenings();
                        break;
                    case 2:
                        addScreening();
                        break;
                    case 3:
                        updateScreening();
                        break;
                    case 4:
                        deleteScreening();
                        break;
                    case 5:
                        autoSchedule();
                        break;
                    case 0:
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            } catch (BusinessException e) {
                System.out.println(e.getMessage());
            }
        }
    }

    private void addScreening() {
        movieManager.listAllMovies();
        System.out.print("选择电影ID: ");
        String movieId = scanner.nextLine();
        Movie movie = movieManager.getMovie(movieId);

        System.out.println("可用影厅: 黄金厅, 白银厅, 翡翠厅, 钻石厅, 宝石厅");
        System.out.print("选择影厅: ");
        String hallName = scanner.nextLine();

        System.out.print("开始时间(格式: yyyy-MM-dd HH:mm): ");
        String timeInput = scanner.nextLine();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        LocalDateTime startTime = LocalDateTime.parse(timeInput, formatter);

        System.out.print("票价: ");
        double price = Double.parseDouble(scanner.nextLine());

        screeningManager.addScreening(movie, hallName, startTime, price);
        System.out.println("场次添加成功");
    }

    private void updateScreening() {
        screeningManager.listScreenings();
        System.out.print("输入要修改的场次ID: ");
        String screeningId = scanner.nextLine();

        movieManager.listAllMovies();
        System.out.print("新电影ID: ");
        String newMovieId = scanner.nextLine();

        System.out.print("新开始时间(格式: yyyy-MM-dd HH:mm): ");
        String timeInput = scanner.nextLine();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        LocalDateTime newStartTime = LocalDateTime.parse(timeInput, formatter);

        System.out.print("新票价: ");
        double newPrice = Double.parseDouble(scanner.nextLine());

        screeningManager.updateScreening(screeningId, newMovieId, newStartTime, newPrice);
        System.out.println("场次更新成功");
    }

    private void deleteScreening() {
        screeningManager.listScreenings();
        System.out.print("输入要删除的场次ID: ");
        String screeningId = scanner.nextLine();

        screeningManager.cancelScreening(screeningId);
        System.out.println("场次删除成功");
    }

    private void autoSchedule() {
        System.out.println("自动排片功能将高分电影安排在黄金时段...");
        screeningManager.autoSchedule();
        System.out.println("自动排片完成!");
    }

    private void salesReportMenu() {
        System.out.println("\n--- 销售报表 ---");
        System.out.println("1. 当日销售数据");
        System.out.println("2. 当周销售数据");
        System.out.println("3. 当月销售数据");
        System.out.print("请选择: ");

        try {
            int choice = Integer.parseInt(scanner.nextLine());

            switch (choice) {
                case 1:
                    ticketManager.showDailyReport();
                    break;
                case 2:
                    ticketManager.showWeeklyReport();
                    break;
                case 3:
                    ticketManager.showMonthlyReport();
                    break;
                default:
                    System.out.println("无效选择");
            }
        } catch (NumberFormatException e) {
            System.out.println("请输入数字选项");
        }
    }

    // 前台菜单
    private void showFrontDeskMenu() {
        while (true) {
            System.out.println("\n===== 前台菜单 =====");
            System.out.println("1. 列出所有影片");
            System.out.println("2. 列出所有场次");
            System.out.println("3. 查看场次座位");
            System.out.println("4. 售票");
            System.out.println("5. 退票");
            System.out.println("6. 退出登录");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        movieManager.listAllMovies();
                        break;
                    case 2:
                        screeningManager.listScreenings();
                        break;
                    case 3:
                        showScreeningSeats();
                        break;
                    case 4:
                        sellTicket();
                        break;
                    case 5:
                        refundTicket();
                        break;
                    case 6:
                        currentUser = null;
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            }
        }
    }

    private void showScreeningSeats() {
        screeningManager.listScreenings();
        System.out.print("输入场次ID: ");
        String screeningId = scanner.nextLine();
        Screening screening = screeningManager.getScreening(screeningId);

        if (screening != null) {
            screening.getHall().displaySeatMap();
        } else {
            System.out.println("场次不存在");
        }
    }

    // 售票功能
    private void sellTicket() {
        screeningManager.listScreenings();
        System.out.print("场次ID: ");
        String screeningId = scanner.nextLine();
        Screening screening = screeningManager.getScreening(screeningId);

        if (screening == null) {
            System.out.println("场次不存在");
            return;
        }

        screening.getHall().displaySeatMap();

        System.out.print("选择行号: ");
        int row = Integer.parseInt(scanner.nextLine()) - 1;
        System.out.print("选择座位号(多个用逗号分隔): ");
        String[] seatNumbers = scanner.nextLine().split(",");

        List<ScreeningHall.Seat> seats = new ArrayList<>();
        for (String num : seatNumbers) {
            int col = Integer.parseInt(num.trim()) - 1;
            ScreeningHall.Seat seat = screening.getHall().getSeat(row, col);
            seats.add(seat);
        }

        System.out.print("是否有儿童票? (y/n): ");
        boolean hasChild = scanner.nextLine().equalsIgnoreCase("y");

        Ticket ticket = ticketManager.sellTicket(screening, seats, hasChild);
        System.out.println("售票成功! 票号: " + ticket.getTicketId());
        System.out.println("总价: " + ticket.getPrice());
    }

    // 退票功能
    private void refundTicket() {
        System.out.print("输入票号: ");
        String ticketId = scanner.nextLine();

        try {
            double refundAmount = ticketManager.refundTicket(ticketId);
            System.out.println("退票成功! 退款金额: " + refundAmount);
        } catch (BusinessException e) {
            System.out.println(e.getMessage());
        }
    }
}

// 枚举和常量
enum UserType {
    ADMIN, MANAGER, FRONT_DESK
}

// 自定义异常
class BusinessException extends RuntimeException {
    public BusinessException(String message) {
        super(message);
    }
}

// 日志工具
class LogUtil {
    public static void log(String operator, String actionType, String details) {
        String logEntry = String.format("[%s] %s - %s: %s",
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
                operator,
                actionType,
                details);

        System.out.println(logEntry);
    }
}

// 用户相关类
abstract class User {
    private String userId;
    private String username;
    private String password;
    private LocalDateTime registerTime;
    private String phone;
    private boolean forcePasswordChange;

    public User(String userId, String username, String password,
                LocalDateTime registerTime, String phone) {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.registerTime = registerTime;
        this.phone = phone;
        this.forcePasswordChange = true;
    }

    public String getUserId() { return userId; }
    public String getUsername() { return username; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = MD5Util.encrypt(password); }
    public LocalDateTime getRegisterTime() { return registerTime; }
    public String getPhone() { return phone; }
    public void setPhone(String phone) { this.phone = phone; }
    public boolean isForcePasswordChange() { return forcePasswordChange; }
    public void setForcePasswordChange(boolean force) { this.forcePasswordChange = force; }

    public boolean verifyPassword(String input) {
        return password.equals(MD5Util.encrypt(input));
    }

    public String toCsvString() {
        return String.format("%s,%s,%s,%s,%s",
                userId, username, password, registerTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME), phone);
    }

    public static User fromCsvString(String csv) {
        String[] parts = csv.split(",");
        if (parts.length < 5) return null;

        String userId = parts[0];
        String username = parts[1];
        String password = parts[2];
        LocalDateTime registerTime = LocalDateTime.parse(parts[3], DateTimeFormatter.ISO_LOCAL_DATE_TIME);
        String phone = parts[4];

        return new Admin(userId, username, password, registerTime, phone);
    }
}

class Admin extends User {
    public Admin(String userId, String username, String password,
                 LocalDateTime registerTime, String phone) {
        super(userId, username, password, registerTime, phone);
    }
}

class Manager extends User {
    public Manager(String userId, String username, String password,
                   LocalDateTime registerTime, String phone) {
        super(userId, username, password, registerTime, phone);
    }
}

class FrontDesk extends User {
    public FrontDesk(String userId, String username, String password,
                     LocalDateTime registerTime, String phone) {
        super(userId, username, password, registerTime, phone);
    }
}

// 用户管理
class UserManager1_1 {
    private List<User> users = new ArrayList<>();
    private Map<String, Integer> userIndexMap = new HashMap<>();

    public UserManager1_1() {
        // 初始化管理员
        addUser(new Admin("ADM001", "admin", MD5Util.encrypt("ynuinfo#777"), LocalDateTime.now(), "13800000000"));
    }

    public void addUser(User user) {
        users.add(user);
        userIndexMap.put(user.getUsername(), users.size() - 1);
    }

    public User authenticate(String username, String password) {
        User user = getUser(username);
        if (user != null && user.verifyPassword(password)) {
            return user;
        }
        return null;
    }

    public User getUser(String username) {
        Integer index = userIndexMap.get(username);
        if (index != null && index < users.size()) {
            return users.get(index);
        }
        return null;
    }

    public void saveUsersToFile() {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(CinemaSystem1.USERS_FILE))) {
            for (User user : users) {
                writer.write(user.toCsvString());
                writer.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void loadUsersFromFile() {
        try (BufferedReader reader = new BufferedReader(new FileReader(CinemaSystem1.USERS_FILE))) {
            String line;
            while ((line = reader.readLine()) != null) {
                User user = User.fromCsvString(line);
                addUser(user);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void resetUserPassword(String username) {
        User user = getUser(username);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        if (user instanceof Admin) {
            throw new BusinessException("不能重置管理员密码");
        }

        user.setPassword("123456");
        user.setForcePasswordChange(true);
    }

    public void resetFrontDeskPassword(String username) {
        User user = getUser(username);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        if (!(user instanceof FrontDesk)) {
            throw new BusinessException("只能重置前台密码");
        }

        user.setPassword("123456");
        user.setForcePasswordChange(true);
    }

    public void listAllUsers() {
        System.out.println("\n用户列表:");
        System.out.printf("%-10s %-15s %-20s %-10s %-15s\n",
                "用户ID", "用户名", "注册时间", "类型", "手机号");

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

        for (User user : users) {
            String type = "未知";
            if (user instanceof Admin) type = "管理员";
            else if (user instanceof Manager) type = "经理";
            else if (user instanceof FrontDesk) type = "前台";

            System.out.printf("%-10s %-15s %-20s %-10s %-15s\n",
                    user.getUserId(),
                    user.getUsername(),
                    user.getRegisterTime().format(formatter),
                    type,
                    user.getPhone());
        }
    }

    public void queryUser(String username) {
        User user = getUser(username);
        if (user == null) {
            System.out.println("用户不存在");
            return;
        }

        String type = "未知";
        if (user instanceof Admin) type = "管理员";
        else if (user instanceof Manager) type = "经理";
        else if (user instanceof FrontDesk) type = "前台";

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

        System.out.println("\n用户信息:");
        System.out.println("用户ID: " + user.getUserId());
        System.out.println("用户名: " + user.getUsername());
        System.out.println("注册时间: " + user.getRegisterTime().format(formatter));
        System.out.println("类型: " + type);
        System.out.println("手机号: " + user.getPhone());
    }

    public void updateUser(String username, UserType newType, String newPhone) {
        User user = getUser(username);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        if (user instanceof Admin) {
            throw new BusinessException("不能修改管理员类型");
        }

        user.setPhone(newPhone);

        User newUser;
        switch (newType) {
            case MANAGER:
                newUser = new Manager(user.getUserId(), user.getUsername(),
                        user.getPassword(), user.getRegisterTime(), newPhone);
                break;
            case FRONT_DESK:
                newUser = new FrontDesk(user.getUserId(), user.getUsername(),
                        user.getPassword(), user.getRegisterTime(), newPhone);
                break;
            default:
                throw new BusinessException("无效用户类型");
        }

        int index = userIndexMap.get(username);
        users.set(index, newUser);
        userIndexMap.put(username, index);
    }

    public void deleteUser(String username) {
        User user = getUser(username);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        if (user instanceof Admin && "admin".equals(username)) {
            throw new BusinessException("不能删除admin用户");
        }

        users.remove(user);
        userIndexMap.remove(username);
    }

    public void addUser(String userId, String username, String phone, UserType userType) {
    }
}

// 放映厅相关类
class ScreeningHall {
    private String hallName;
    private int rows;
    private int cols;
    private Seat[][] seats;

    public ScreeningHall(String name, int rows, int cols) {
        this.hallName = name;
        this.rows = rows;
        this.cols = cols;
        initializeSeats();
    }

    private void initializeSeats() {
        seats = new Seat[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                seats[i][j] = new Seat(i, j);
            }
        }
    }

    public String getHallName() { return hallName; }
    public int getRows() { return rows; }
    public int getCols() { return cols; }
    public Seat getSeat(int row, int col) {
        if (row < 0 || row >= rows || col < 0 || col >= cols) {
            throw new BusinessException("座位不存在");
        }
        return seats[row][col];
    }

    public void displaySeatMap() {
        System.out.println("\n座位图 (" + hallName + "):");
        System.out.print("   ");
        for (int j = 0; j < cols; j++) {
            System.out.printf("%2d ", j + 1);
        }
        System.out.println();

        for (int i = 0; i < rows; i++) {
            System.out.printf("%2d ", i + 1);
            for (int j = 0; j < cols; j++) {
                System.out.print(seats[i][j].isAvailable() ? " O " : " X ");
            }
            System.out.println();
        }
        System.out.println("O: 空座  X: 已售");
    }

    class Seat {
        private int row;
        private int col;
        private boolean available;

        public Seat(int row, int col) {
            this.row = row;
            this.col = col;
            this.available = true;
        }

        public int getRow() { return row; }
        public int getCol() { return col; }
        public boolean isAvailable() { return available; }
        public void setAvailable(boolean available) { this.available = available; }
    }
}

// 电影相关类
class Movie {
    private String movieId;
    private String title;
    private String director;
    private String[] stars;
    private String description;
    private int duration;
    private double rating;

    public Movie(String movieId, String title, String director, String[] stars,
                 String description, int duration, double rating) {
        this.movieId = movieId;
        this.title = title;
        this.director = director;
        this.stars = stars;
        this.description = description;
        this.duration = duration;
        setRating(rating);
    }

    public String getMovieId() { return movieId; }
    public String getTitle() { return title; }
    public String getDirector() { return director; }
    public String[] getStars() { return stars; }
    public String getDescription() { return description; }
    public int getDuration() { return duration; }
    public double getRating() { return rating; }

    public void setTitle(String title) { this.title = title; }
    public void setDirector(String director) { this.director = director; }
    public void setStars(String[] stars) { this.stars = stars; }
    public void setDescription(String description) { this.description = description; }
    public void setDuration(int duration) { this.duration = duration; }
    public void setRating(double rating) {
        if (rating < 0 || rating > 10) {
            throw new BusinessException("评分必须在0-10之间");
        }
        this.rating = rating;
    }

    public String toCsvString() {
        return String.format("%s,%s,%s,%s,%d,%.1f",
                movieId, title, director, String.join(",", stars), duration, rating);
    }

    public static Movie fromCsvString(String csv) {
        String[] parts = csv.split(",");
        if (parts.length < 6) return null;

        String movieId = parts[0];
        String title = parts[1];
        String director = parts[2];
        String[] stars = parts[3].split(",");
        int duration = Integer.parseInt(parts[4]);
        double rating = Double.parseDouble(parts[5]);

        return new Movie(movieId, title, director, stars, "", duration, rating);
    }
}

// 电影管理类
class MovieManager1_1 {
    private List<Movie> movies = new ArrayList<>();
    private Map<String, Integer> movieIdToIndexMap = new HashMap<>();
    private AtomicInteger movieCounter = new AtomicInteger(1);

    public void addMovie(String title, String director, String[] stars,
                         String description, int duration, double rating) {
        String movieId = "MOV" + movieCounter.getAndIncrement();
        Movie movie = new Movie(movieId, title, director, stars, description, duration, rating);
        movies.add(movie);
        movieIdToIndexMap.put(movieId, movies.size() - 1);
    }

    public Movie getMovie(String movieId) {
        Integer index = movieIdToIndexMap.get(movieId);
        if (index != null && index < movies.size()) {
            return movies.get(index);
        }
        return null;
    }

    public void listAllMovies() {
        if (movies.isEmpty()) {
            System.out.println("暂无影片信息");
            return;
        }

        System.out.println("\n影片列表:");
        System.out.printf("%-10s %-20s %-15s %-50s %-8s %-6s\n",
                "ID", "片名", "导演", "主演", "时长", "评分");

        for (Movie movie : movies) {
            System.out.printf("%-10s %-20s %-15s %-50s %-8d %-6.1f\n",
                    movie.getMovieId(),
                    movie.getTitle(),
                    movie.getDirector(),
                    String.join(", ", movie.getStars()),
                    movie.getDuration(),
                    movie.getRating());
        }
    }

    public void updateMovie(String movieId, String title, String director, String[] stars,
                            String description, int duration, double rating) {
        Movie movie = getMovie(movieId);
        if (movie == null) {
            throw new BusinessException("影片不存在");
        }

        movie.setTitle(title);
        movie.setDirector(director);
        movie.setStars(stars);
        movie.setDescription(description);
        movie.setDuration(duration);
        movie.setRating(rating);
    }

    public void deleteMovie(String movieId) {
        if (!movieIdToIndexMap.containsKey(movieId)) {
            throw new BusinessException("影片不存在");
        }

        movies.remove(movieIdToIndexMap.get(movieId));
        movieIdToIndexMap.remove(movieId);
    }

    public void searchMovies(String keyword) {
        List<Movie> results = new ArrayList<>();
        String lowerKeyword = keyword.toLowerCase();

        for (Movie movie : movies) {
            if (movie.getTitle().toLowerCase().contains(lowerKeyword) ||
                    movie.getDirector().toLowerCase().contains(lowerKeyword) ||
                    String.join(",", movie.getStars()).toLowerCase().contains(lowerKeyword)) {
                results.add(movie);
            }
        }

        if (results.isEmpty()) {
            System.out.println("未找到相关影片");
            return;
        }

        System.out.println("\n搜索结果:");
        System.out.printf("%-10s %-20s %-15s %-50s %-8s %-6s\n",
                "ID", "片名", "导演", "主演", "时长", "评分");

        for (Movie movie : results) {
            System.out.printf("%-10s %-20s %-15s %-50s %-8d %-6.1f\n",
                    movie.getMovieId(),
                    movie.getTitle(),
                    movie.getDirector(),
                    String.join(", ", movie.getStars()),
                    movie.getDuration(),
                    movie.getRating());
        }
    }

    public void saveMoviesToFile() {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(CinemaSystem1.MOVIES_FILE))) {
            for (Movie movie : movies) {
                writer.write(movie.toCsvString());
                writer.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void loadMoviesFromFile() {
        try (BufferedReader reader = new BufferedReader(new FileReader(CinemaSystem1.MOVIES_FILE))) {
            String line;
            while ((line = reader.readLine()) != null) {
                Movie movie = Movie.fromCsvString(line);
                if (movie != null) {
                    addMovie(movie.getTitle(), movie.getDirector(), movie.getStars(),
                            movie.getDescription(), movie.getDuration(), movie.getRating());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public List<Movie> getAllMovies() {
        return new ArrayList<>(movies);
    }
}

// 放映场次类
class Screening {
    private String screeningId;
    private Movie movie;
    private ScreeningHall hall;
    private LocalDateTime startTime;
    private double price;
    private boolean cancelled;

    public Screening(String screeningId, Movie movie, ScreeningHall hall,
                     LocalDateTime startTime, double price) {
        this.screeningId = screeningId;
        this.movie = movie;
        this.hall = hall;
        this.startTime = startTime;
        this.price = price;
        this.cancelled = false;
    }

    public String getScreeningId() { return screeningId; }
    public Movie getMovie() { return movie; }
    public ScreeningHall getHall() { return hall; }
    public LocalDateTime getStartTime() { return startTime; }
    public double getPrice() { return price; }
    public boolean isCancelled() { return cancelled; }

    public void setMovie(Movie movie) { this.movie = movie; }
    public void setStartTime(LocalDateTime startTime) { this.startTime = startTime; }
    public void setPrice(double price) { this.price = price; }
    public void setCancelled(boolean cancelled) { this.cancelled = cancelled; }
}

// 排片管理类
class ScreeningManager1_1 {
    private Map<String, Screening> screenings = new HashMap<>();
    private Map<String, ScreeningHall> halls;
    private MovieManager1_1 movieManager;
    private TicketManager1_1 ticketManager;
    private AtomicInteger screeningCounter = new AtomicInteger(1);

    public ScreeningManager1_1(Map<String, ScreeningHall> halls,
                               MovieManager1_1 movieManager,
                               TicketManager1_1 ticketManager) {
        this.halls = halls;
        this.movieManager = movieManager;
        this.ticketManager = ticketManager;
    }

    public void addScreening(Movie movie, String hallName, LocalDateTime startTime, double price) {
        ScreeningHall hall = halls.get(hallName);
        if (hall == null) {
            throw new BusinessException("影厅不存在");
        }

        if (startTime.isBefore(LocalDateTime.now().plusHours(1))) {
            throw new BusinessException("场次时间至少在当前时间1小时后");
        }

        if (startTime.isAfter(LocalDateTime.now().plusDays(7))) {
            throw new BusinessException("只能安排未来7天内的场次");
        }

        String screeningId = "SCR" + screeningCounter.getAndIncrement();
        Screening screening = new Screening(screeningId, movie, hall, startTime, price);
        screenings.put(screeningId, screening);
    }

    public Screening getScreening(String screeningId) {
        return screenings.get(screeningId);
    }

    public void listScreenings() {
        if (screenings.isEmpty()) {
            System.out.println("暂无场次信息");
            return;
        }

        System.out.println("\n场次列表:");
        System.out.printf("%-10s %-20s %-10s %-20s %-8s %-6s\n",
                "ID", "影片", "影厅", "开始时间", "票价", "状态");

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd HH:mm");

        for (Screening screening : screenings.values()) {
            String status = screening.isCancelled() ? "已取消" : "正常";
            System.out.printf("%-10s %-20s %-10s %-20s %-8.1f %-6s\n",
                    screening.getScreeningId(),
                    screening.getMovie().getTitle(),
                    screening.getHall().getHallName(),
                    screening.getStartTime().format(formatter),
                    screening.getPrice(),
                    status);
        }
    }

    public void updateScreening(String screeningId, String newMovieId,
                                LocalDateTime newStartTime, double newPrice) {
        Screening screening = screenings.get(screeningId);
        if (screening == null) {
            throw new BusinessException("场次不存在");
        }

        if (ticketManager.hasTicketsForScreening(screeningId)) {
            throw new BusinessException("该场次已有售票，无法修改");
        }

        Movie newMovie = movieManager.getMovie(newMovieId);
        if (newMovie == null) {
            throw new BusinessException("影片不存在");
        }

        screening.setMovie(newMovie);
        screening.setStartTime(newStartTime);
        screening.setPrice(newPrice);
    }

    public void cancelScreening(String screeningId) {
        Screening screening = screenings.get(screeningId);
        if (screening == null) {
            throw new BusinessException("场次不存在");
        }

        if (ticketManager.hasTicketsForScreening(screeningId)) {
            throw new BusinessException("该场次已有售票，无法取消");
        }

        screening.setCancelled(true);
    }

    public void autoSchedule() {
        List<Movie> movies = movieManager.getAllMovies();
        movies.sort((m1, m2) -> Double.compare(m2.getRating(), m1.getRating()));

        if (movies.isEmpty()) {
            System.out.println("没有可排片的影片");
            return;
        }

        Movie topMovie = movies.get(0);
        LocalDateTime primeTime = LocalDateTime.now().plusDays(5).withHour(19).withMinute(30);

        addScreening(topMovie, "黄金厅", primeTime, 50.0);

        if (movies.size() > 1) {
            Movie secondMovie = movies.get(1);
            LocalDateTime secondPrimeTime = LocalDateTime.now().plusDays(1).withHour(14).withMinute(0);
            addScreening(secondMovie, "白银厅", secondPrimeTime, 40.0);
        }

        if (movies.size() > 2) {
            Movie thirdMovie = movies.get(2);
            LocalDateTime thirdPrimeTime = LocalDateTime.now().plusDays(3).withHour(21).withMinute(0);
            addScreening(thirdMovie, "翡翠厅", thirdPrimeTime, 45.0);
        }
    }
}

// 电影票类
class Ticket {
    private String ticketId;
    private Screening screening;
    private List<ScreeningHall.Seat> seats;
    private double price;
    private LocalDateTime purchaseTime;
    private boolean refunded;
    private LocalDateTime refundTime;
    private double refundedAmount;

    public Ticket(Screening screening, List<ScreeningHall.Seat> seats, boolean hasChild) {
        this.ticketId = UUID.randomUUID().toString();
        this.screening = screening;
        this.seats = seats;
        this.purchaseTime = LocalDateTime.now();
        this.refunded = false;
        calculatePrice(hasChild);
    }

    private void calculatePrice(boolean hasChild) {
        double basePrice = screening.getPrice() * seats.size();

        if (hasChild) {
            basePrice *= 0.5;
        }

        if (screening.getStartTime().getHour() < 10) {
            basePrice *= 0.9;
        }

        this.price = basePrice;
    }

    public String getTicketId() { return ticketId; }
    public Screening getScreening() { return screening; }
    public List<ScreeningHall.Seat> getSeats() { return seats; }
    public double getPrice() { return price; }
    public LocalDateTime getPurchaseTime() { return purchaseTime; }
    public boolean isRefunded() { return refunded; }
    public LocalDateTime getRefundTime() { return refundTime; }
    public double getRefundedAmount() { return refundedAmount; }
    public void setRefunded(boolean refunded) { this.refunded = refunded; }

    public void setRefundInfo(double amount) {
        this.refundedAmount = amount;
        this.refundTime = LocalDateTime.now();
    }

    public boolean canRefund() {
        return LocalDateTime.now().isBefore(screening.getStartTime().minusHours(1)) && !refunded;
    }
}

// 票务管理类
class TicketManager1_1 {
    private Map<String, Ticket> tickets = new HashMap<>();

    public Ticket sellTicket(Screening screening, List<ScreeningHall.Seat> seats, boolean hasChild) {
        for (ScreeningHall.Seat seat : seats) {
            if (!seat.isAvailable()) {
                throw new BusinessException("座位已被占用");
            }
        }

        Ticket ticket = new Ticket(screening, seats, hasChild);

        for (ScreeningHall.Seat seat : seats) {
            seat.setAvailable(false);
        }

        tickets.put(ticket.getTicketId(), ticket);
        return ticket;
    }

    public double refundTicket(String ticketId) {
        Ticket ticket = tickets.get(ticketId);
        if (ticket == null) {
            throw new BusinessException("票号无效");
        }

        if (!ticket.canRefund()) {
            throw new BusinessException("开场前1小时内不可退票");
        }

        double refundAmount = ticket.getPrice();
        if (LocalDateTime.now().isAfter(ticket.getScreening().getStartTime().minusDays(1))) {
            refundAmount *= 0.9;
        }

        ticket.setRefundInfo(refundAmount);
        ticket.setRefunded(true);

        for (ScreeningHall.Seat seat : ticket.getSeats()) {
            seat.setAvailable(true);
        }

        return refundAmount;
    }

    public boolean hasTicketsForScreening(String screeningId) {
        for (Ticket ticket : tickets.values()) {
            if (ticket.getScreening().getScreeningId().equals(screeningId) && !ticket.isRefunded()) {
                return true;
            }
        }
        return false;
    }

    public void showDailyReport() {
        LocalDate today = LocalDate.now();
        double totalSales = 0;
        double totalRefunds = 0;
        int ticketsSold = 0;
        int ticketsRefunded = 0;

        for (Ticket ticket : tickets.values()) {
            if (ticket.getPurchaseTime().toLocalDate().equals(today)) {
                totalSales += ticket.getPrice();
                ticketsSold++;
            }

            if (ticket.isRefunded() && ticket.getRefundTime().toLocalDate().equals(today)) {
                totalRefunds += ticket.getRefundedAmount();
                ticketsRefunded++;
            }
        }

        System.out.println("\n当日销售报告:");
        System.out.println("售票数量: " + ticketsSold);
        System.out.println("售票金额: " + totalSales);
        System.out.println("退票数量: " + ticketsRefunded);
        System.out.println("退款金额: " + totalRefunds);
        System.out.println("净销售额: " + (totalSales - totalRefunds));
    }

    public void showWeeklyReport() {
        LocalDate today = LocalDate.now();
        LocalDate weekStart = today.minusDays(today.getDayOfWeek().getValue() - 1);
        LocalDate weekEnd = weekStart.plusDays(6);

        double totalSales = 0;
        double totalRefunds = 0;
        int ticketsSold = 0;
        int ticketsRefunded = 0;

        for (Ticket ticket : tickets.values()) {
            LocalDate purchaseDate = ticket.getPurchaseTime().toLocalDate();
            if (!purchaseDate.isBefore(weekStart) && !purchaseDate.isAfter(weekEnd)) {
                totalSales += ticket.getPrice();
                ticketsSold++;
            }

            if (ticket.isRefunded()) {
                LocalDate refundDate = ticket.getRefundTime().toLocalDate();
                if (!refundDate.isBefore(weekStart) && !refundDate.isAfter(weekEnd)) {
                    totalRefunds += ticket.getRefundedAmount();
                    ticketsRefunded++;
                }
            }
        }

        System.out.println("\n本周销售报告 (" + weekStart + " 至 " + weekEnd + "):");
        System.out.println("售票数量: " + ticketsSold);
        System.out.println("售票金额: " + totalSales);
        System.out.println("退票数量: " + ticketsRefunded);
        System.out.println("退款金额: " + totalRefunds);
        System.out.println("净销售额: " + (totalSales - totalRefunds));
    }

    public void showMonthlyReport() {
        YearMonth currentMonth = YearMonth.now();
        LocalDate monthStart = currentMonth.atDay(1);
        LocalDate monthEnd = currentMonth.atEndOfMonth();

        double totalSales = 0;
        double totalRefunds = 0;
        int ticketsSold = 0;
        int ticketsRefunded = 0;

        for (Ticket ticket : tickets.values()) {
            LocalDate purchaseDate = ticket.getPurchaseTime().toLocalDate();
            if (!purchaseDate.isBefore(monthStart) && !purchaseDate.isAfter(monthEnd)) {
                totalSales += ticket.getPrice();
                ticketsSold++;
            }

            if (ticket.isRefunded()) {
                LocalDate refundDate = ticket.getRefundTime().toLocalDate();
                if (!refundDate.isBefore(monthStart) && !refundDate.isAfter(monthEnd)) {
                    totalRefunds += ticket.getRefundedAmount();
                    ticketsRefunded++;
                }
            }
        }

        System.out.println("\n本月销售报告 (" + monthStart + " 至 " + monthEnd + "):");
        System.out.println("售票数量: " + ticketsSold);
        System.out.println("售票金额: " + totalSales);
        System.out.println("退票数量: " + ticketsRefunded);
        System.out.println("退款金额: " + totalRefunds);
        System.out.println("净销售额: " + (totalSales - totalRefunds));
    }
}

// MD5加密工具类
class MD5Util {
    public static String encrypt(String str) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] array = md.digest(str.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString();
        } catch (Exception e) {
            throw new RuntimeException("MD5加密出错");
        }
    }
}